﻿using System;
using System.Linq;
using System.Reactive.Linq;
using System.Threading;
using System.Windows.Input;
using NUnit.Framework;
using Present.Commands.Decorators;
using Rhino.Mocks;

namespace Present.Commands.Tests.Decorators
{
    [TestFixture]
    public class ScheduledCommandDecoratorTestCase : TestCase
    {
        private ICommand innerCommand;
        private ScheduledCommandDecorator<ICommand> command;

        public override void Setup()
        {
            base.Setup();
            innerCommand = MockRepository.GenerateStub<ICommand>();
            command = new ScheduledCommandDecorator<ICommand>(innerCommand);

        }

        [Test, Ignore("Need a good way to test this, waiting to see what TestScheduler is all about in new Rx")]
       public void InnerCommandIsScheduledOnUiThread()
       {
            command.Schedule = Observable.Interval(TimeSpan.FromMilliseconds(10));
            Thread.Sleep(100);

           // AssertWasScheduledOnUiThread();

       }


       [Test]
       public void CanSchedule()
       {
           command.Schedule = Observable.Interval(TimeSpan.FromMilliseconds(10));
           Thread.Sleep(100);
           innerCommand.AssertWasCalled(x=>x.Execute(null), o => o.Repeat.Times(5, 15));
       }

        [Test]
        public void CanStopSchedule()
        {
            command.Schedule = Observable.Interval(TimeSpan.FromMilliseconds(100));
            command.Enabled = false;
            Thread.Sleep(150);
            innerCommand.AssertWasNotCalled(x => x.Execute(null));

        }


        [Test]
        public void CanSetScheduleWhileBeingDisabledAndThenEnable()
        {
            command.Enabled = false;
            command.Schedule = Observable.Interval(TimeSpan.FromMilliseconds(10));
            Thread.Sleep(100);
            innerCommand.AssertWasNotCalled(x => x.Execute(null));
            command.Enabled = true;
            Thread.Sleep(100);
            innerCommand.AssertWasCalled(x => x.Execute(null));

        }

        [Test]
        public void CanStopThenStartSchedule()
        {
            command.Schedule = Observable.Interval(TimeSpan.FromMilliseconds(100));
            command.Enabled = false;
            command.Enabled = true;
            Thread.Sleep(150);
            innerCommand.AssertWasCalled(x => x.Execute(null));
        }

        [Test]
        public void ShouldStopScheduleWhenDisposed()
        {
            command.Schedule = Observable.Interval(TimeSpan.FromMilliseconds(100));
            command.Dispose();
            innerCommand.AssertWasNotCalled(x => x.Execute(null), o => o.Repeat.Times(0, 1));

        }
        
    }
}
